package ServePackage;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.esotericsoftware.kryonet.*;
public class ServerApplication extends Listener  {
	public static Map<String,List<Player>> RoomList;
	private static Server server;
	static int udpPort=9988;
	static int tcpPort=9999;
	static PacketMessage pmessage;
	public static void main(String[] args)throws Exception
	{
	  Initialize();
	  System.out.println("Creating The Server.........");
	  server= new Server();
	  server.getKryo().register(PacketMessage.class);
	  server.bind(tcpPort,udpPort);
	  server.start();
	  System.out.println("Server is working.....");
	  server.addListener(new ServerApplication());
	  }
    public void connected(Connection c)
    {
       System.out.println("Get Message From"+c.getRemoteAddressTCP().getHostString());
       pmessage.setMessage("Connected-to-server");
       c.sendUDP(pmessage); 
    }
    public void received(Connection c,Object p)
	{
		if(p instanceof PacketMessage)
		{
			PacketMessage packet= (PacketMessage)p;
			try
			{
			protocol(packet.getMessage(),c);
			}
			catch(Exception e)
			{
			
			}
		    	
		}
	
	}
    public void disconnected(Connection c)
    {
      System.out.println("Disconnected from Server");
      try
     	{
    	 	notifyDisconnect(c);
     	}
     catch(Exception e)
     	{
	
     	}
    }
    
    public void notifyDisconnect(Connection c)
    {
    	List<Player> pList=new ArrayList<Player>();
    	String disconnectedPlayerName="";
    	Player disconnectedPlayer=new Player();
    	Map.Entry<String,List<Player>> ent=null;
        for(Map.Entry<String,List<Player>> entry:RoomList.entrySet())
        {
        	for(Player p: entry.getValue())
        	{
        	    if(p.connection.equals(c))
        	    {
        	    	disconnectedPlayer=p;
        	    	disconnectedPlayerName=p.Name;
        	    	pList=entry.getValue();
        	    	ent=entry;
        	    	break;
        	    }
        	}
        }
        pList.remove(disconnectedPlayer);
        if(pList.size()==0&&ent!=null)
        DestroyRoom(ent.getKey());
        for(Player p: pList)
        {   p.isHost="Host";
        	pmessage.setMessage("Disconnected"+"-"+disconnectedPlayerName);
        	p.connection.sendTCP(pmessage);
        }
        
    }

    public void protocol(String message, Connection c)
    {
    	
    	String[] SpliteMessage=procees_string(message);
    	for(String s: SpliteMessage)
    	{
    	 System.out.println(s);
    	}
    	if(SpliteMessage[0].equals("CreateRoom"))
    	{
    		List<Player>playerlist= new ArrayList<Player>();
    		playerlist.add(new Player(SpliteMessage[2],c,"Host"));
    		pmessage.setMessage("Room "+SpliteMessage[1]+" created succesfully");
    		RoomList.put(SpliteMessage[1],playerlist);
    	    c.sendTCP(pmessage);
    	}	
    	else if (SpliteMessage[0].equals("JoinRoom"))
    	{
    		boolean found =false;
    	   for(Map.Entry<String,List<Player>> entry:RoomList.entrySet())
    	   {
    		   if(entry.getKey().equals(SpliteMessage[1])&&entry.getValue().size()<2)
    		   {
    		      entry.getValue().add(new Player(SpliteMessage[2],c,"Guest"));
    		      for(Player pl:entry.getValue())
    		      {
	    		      pmessage.setMessage("JoinedRoom"+"-"+SpliteMessage[2]);
	    		      pl.connection.sendTCP(pmessage);
    		      }
    		      found=true;
    		      break;
    		   }
    		   else if(entry.getKey().equals(SpliteMessage[1])&&entry.getValue().size()==2)
    		   {
    		      pmessage.setMessage("Room full");
    		      c.sendTCP(pmessage);
    		      found=true;
    		   }
    	   }
    	   if(!found)
    	   {
		    	   pmessage.setMessage("Room Not Found");
				   c.sendTCP(pmessage);
    	   }
    	}
    	else if(SpliteMessage[0].equals("SendMessage"))
    	{
    		System.out.println("kirimPesan");
    		SendToRoom(RoomList.get(SpliteMessage[1]),SpliteMessage[2],SpliteMessage[4],SpliteMessage[3]);
    	}
    	else if(SpliteMessage[0].equals("GetPlayerList"))
    	{
            List<Player> p=RoomList.get(SpliteMessage[1]);
            String playersName="";
            for(Player pl : p)
            {
                playersName+=pl.Name+"-";
            }
            pmessage.setMessage("PlayerList-"+playersName);
            c.sendTCP(pmessage);
    	}
    	else if(SpliteMessage[0].equals("GetRoomList"))
    	{
    	   if(RoomList.size()>0)
    	   { String rooms="";
    		   for(Map.Entry<String, List<Player>> entry : RoomList.entrySet())
    		   {if(entry.getValue().size()<=2)
    			rooms+=entry.getKey()+"-";  
    		   }
    		 pmessage.setMessage("RoomList-"+rooms);
    		 c.sendTCP(pmessage);
    	   }
    	   else 
    	   {
    	     pmessage.setMessage("no room alvaible");
    	     c.sendTCP(pmessage);
    	   }
    	 
    	}
    	else if(SpliteMessage[0].equals("Confirmation"))
    	{
    		for(Map.Entry<String, List<Player>> entry : RoomList.entrySet())
    		{
	    		 if(entry.getKey().equals(SpliteMessage[1]))
	    		 {
	    		      for(Player p : entry.getValue())
	    		      {   pmessage.setMessage("Chat-"+SpliteMessage[2]+">>ConfirmationForplay");
	    		    	  p.connection.sendTCP(pmessage);
	    		    	  if(p.Name.equals(SpliteMessage[2]))
		    			  {
		    			    p.Confirmation="Confirm";
		    			    
		    			  }
	    		      }
	    		      break;
	    		      
	    		 }
    		}
    	}
    	else if(SpliteMessage[0].equals("CheckHost"))
    	{
    	   for(Map.Entry<String, List<Player>> entry : RoomList.entrySet())	
    	   {
    	     if(entry.getKey().equals(SpliteMessage[1]))
    	     { 
	    		  for(Player p : entry.getValue())
	    		 { 
	    		   	if(p.Name.equals(SpliteMessage[2]))
	    		   	{  
	    		   	    pmessage.setMessage("IsHost"+"-"+p.isHost);
	    		   		p.connection.sendTCP(pmessage);
	    		   	}
	             }
    	     }
    	   }
    	}
    	else if(SpliteMessage[0].equals("StartGame"))
    	{
    		boolean isConfirmed=true;
    		List<Player>plRoom= new ArrayList<Player>();
    		for(Map.Entry<String, List<Player>> entry : RoomList.entrySet())
    		{
	    		 if(entry.getKey().equals(SpliteMessage[1]))
	    		 { 	plRoom=entry.getValue();
	    		      for(Player p : entry.getValue())
	    		      {
	    		    	if(!p.Confirmation.equals("Confirm"))
	    		    	{ 
	    		    		isConfirmed=false;
	    		    	}
	    		      }
	    		      
	    		      break;
	    		 }
	    		 
    		}
    		if(isConfirmed)
    		{  System.out.println("confirmed");
    		   SendToRoom(plRoom,"","StartGame","StartGame");
    		}
    	}
    	else if(SpliteMessage[0].equals("EndTurn"))
    	{
    		for(Map.Entry<String, List<Player>> entry : RoomList.entrySet())	
     	   {
     	     if(entry.getKey().equals(SpliteMessage[1]))
     	     { 
 	    		  for(Player p : entry.getValue())
 	    		 {      if(!p.Name.equals(SpliteMessage[2]))
 	    		 		{
 	    		   	    pmessage.setMessage("EndTurn");
 	    		   		p.connection.sendTCP(pmessage);
 	    		 		}
 	             }
     	     }
     	   }
    	}
    	else if(SpliteMessage[0].equalsIgnoreCase("LoadFinish"))
    	{
    		List<Player>room= RoomList.get(SpliteMessage[1]);
    		int counterfinish=0;
    	    for(Player p: room)
    	    {   if(p.Name.equals(SpliteMessage[2]))
  	    	    {
  	    	      p.isFinish=true;
  	    	    }
    	    }
    	    for(Player p: room)
    	    {   if(p.isFinish)
  	    	    {
  	    	     counterfinish++;
  	    	    }
    	    }
    	    if(counterfinish==2)
    	    {
    	    	SendToRoom(room,SpliteMessage[2],"LoadFinish","LoadFinish");
    	    }
    	}
    	else if(SpliteMessage[0].equals("GameEnd"))
    	{
    		DestroyRoom(SpliteMessage[1]);
    	}
    	
   	}
    
    public void SendToRoom(List<Player>PlayerRoom,String PlayerName,String Message,String Protocol)
    {  int random=RandomRange(1,2);
       for(Player p : PlayerRoom)
       {   if(Protocol.equals("CardEffect"))
    	    Protocol+="-"+PlayerName;
    	    pmessage.setMessage(Protocol+"-"+Message+"-"+random);
           p.connection.sendTCP(pmessage);
           System.out.println("Cetak Pesan:"+pmessage.getMessage());
       }
    }
    
    public static void Initialize()
    {
    	RoomList=new HashMap<String,List<Player>>();
        pmessage= new PacketMessage();
    	//for(int c=0;c<5;c++)
    //	{   
    //		List<Player> player= new ArrayList<Player>();
    //	    RoomList.put("Room"+c, player);
    //	}
    	
    }
    public String[] procees_string(String message)
    {
    	 String[] result= message.split("-");
    	 return result;
    }
    
    public void DestroyRoom(String RoomName)
    {
    	RoomList.remove(RoomName);
    }
    public int RandomRange(int min, int max)
    {
       int range=(max-min)+1;
       return (int) (Math.random() *range)+min;
    }
    
    }

